package com.sondon.dev_soceket.tcp.util;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.sondon.dev_soceket.config.ID_MAP;
import com.sondon.dev_soceket.config.MYID;
import com.sondon.dev_soceket.model.TCPEntity;

import sun.misc.CRC16;

public class CodeUtil {
	static CRC16 crc16 = new CRC16();

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月2日 上午11:38:33
	 * @Description { byte[]数组转为16进制字符串 }
	 * @param b
	 */
	public static String printHexString(byte[] b, int size) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < size; i++) {
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			sb.append(hex);
		}
		// 字母大写
		return sb.toString().toUpperCase().trim();
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月2日 下午3:35:43
	 * @Description { byte数组组合在一起 }
	 * @param byte_1
	 * @param byte_2
	 * @return
	 */
	// java 合并两个byte数组
	public static byte[] byteMerger(byte[] byte_1, byte[] byte_2,
			int recvMsgSize) {
		byte[] byte_3 = new byte[byte_1.length + recvMsgSize];
		System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
		System.arraycopy(byte_2, 0, byte_3, byte_1.length, recvMsgSize);
		return byte_3;
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月8日 上午9:51:18
	 * @Description {String转为16进制的byte数组}
	 * @param hexString
	 * @return
	 */
	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月8日 上午9:52:01
	 * @Description {16进制的字符--0123456789ABCDEF}
	 * @param c
	 * @return
	 */
	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月10日 下午2:57:29
	 * @Description {
	 *              举个例子说明，我的机子是32位windows的系统，处理器是AMD的。对于一个int型数0x12345678,为方便说明
	 *              ，这里采用16进制表示。 这个数在不同字节顺序存储的CPU中储存顺序如下：0x12345678
	 *              16进制，两个数就是一字节。 高有效字节——>低有效字节： 12 34 56 78 高低址位 低地址位 大端： 78
	 *              56 12 34 小端： （后）12 34 78 56 （前）
	 * 
	 *              将int转为低字节在前，高字节在后的byte数组 ----小端 }
	 * @param n
	 * @return
	 */
	public static byte[] toLH(int n) {
		byte[] b = new byte[4];
		b[0] = (byte) (n & 0xff);
		b[1] = (byte) (n >> 8 & 0xff);
		b[2] = (byte) (n >> 16 & 0xff);
		b[3] = (byte) (n >> 24 & 0xff);
		return b;
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月10日 下午2:48:27
	 * @Description { CRC16校验 返回16进制的小端字符串 }
	 * @param bytes
	 * @return
	 */
	public static String CRC16Table(byte[] bytes) {
		int[] table = {
				// CRC16原始数据表
				0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
				0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
				0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0X0E40,
				0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
				0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
				0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
				0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
				0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
				0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
				0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
				0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
				0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
				0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
				0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
				0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
				0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
				0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
				0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
				0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
				0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
				0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
				0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
				0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
				0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
				0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
				0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
				0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
				0X5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
				0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
				0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
				0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
				0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, };

		int crc = 0x0000;
		for (byte b : bytes) {
			crc = (crc >> 8) ^ table[(crc ^ b) & 0xff];
		}
		return IntToHexString(crc);
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月10日 下午5:49:14
	 * @Description { 16进制的大端小端字符串互相转换}
	 * @param str
	 * @return
	 */
	public static String HexString_LenOrBig(String str) {
		StringBuffer sb = new StringBuffer();
		int len = str.length();
		// 判断是否奇数
		if (len % 2 > 0) {
			str = 0 + str;
		}
		for (int i = str.length(); 1 < i; i = i - 2) {
			sb.append(str.substring(i - 2, i));
		}
		return sb.toString().trim().toUpperCase();
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月10日 下午5:47:59
	 * @Description { 16进制的小端字符串转为整型 }
	 * @param str
	 * @return
	 */
	public static int HexStringToInt(String str) {
		String result = HexString_LenOrBig(str);
		return Integer.parseInt(result, 16);
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月10日 下午6:19:53
	 * @Description { 整型转为16进制的小端字符串 }
	 * @param a
	 * @return
	 */
	public static String IntToHexString(int a) {
		String str = Integer.toHexString(a);
		return HexString_LenOrBig(str);

	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月16日 下午5:38:01
	 * @Description {字符整型数据转换为16进制的小端字符串 }
	 * @param str_int
	 * @return
	 */
	public static String StrIntToHexString(String str_int) {
		int num = Integer.valueOf(str_int);
		return IntToHexString(num);
	}

	/**
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月10日 下午6:19:53
	 * @Description { 字符串中含有多少个指定字符 }
	 * @param contain_str
	 * @param data_str
	 * @return
	 */
	public static int getContain_StrCount(String contain_str, String data_str) {
		int count = 0;
		int len = data_str.length();
		if (data_str.contains(contain_str)) {
			data_str = data_str.replace(contain_str, "");
			count = (len - data_str.length()) / contain_str.length();
		}
		return count;
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月16日 下午5:46:38
	 * @Description { 返回符合 网管回应设备 协议格式的日期 }
	 * @param is_register
	 * @return
	 */
	public static String getRegisterDate(boolean is_register) {
		// 1 服务器注册回复成功 2 服务器注册回复失败
		int register_seccess = 2;
		if (is_register) {
			register_seccess = 1;
		}
		// 获取当前的年月日时分秒
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy#MM#dd#HH#mm#ss");
		Date d = new Date();
		String format_date = sdf.format(d);
		// 解析拆分年月日时分秒
		String[] strs = format_date.split("#");
		String date = "0200"// ID_CNT ID个数
				+ CodeUtil.IntToHexString(24583)// ID_0
				// ID_0_DATA_INFO 1 服务器注册回复成功 2 服务器注册回复失败
				+ CodeUtil.IntToHexString(register_seccess)
				+ CodeUtil.IntToHexString(24584)// ID_1
				// ID_1_DATA_INFO 年月日时分秒
				+ CodeUtil.StrIntToHexString(strs[5])// 秒
				+ CodeUtil.StrIntToHexString(strs[4])// 分
				+ CodeUtil.StrIntToHexString(strs[3])// 时
				+ CodeUtil.StrIntToHexString(strs[2])// 日
				+ CodeUtil.StrIntToHexString(strs[1])// 月
				+ CodeUtil.StrIntToHexString(strs[0]);// 年

		return date;
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月16日 下午5:53:25
	 * @Description { 获取CRC16校验，返回16进制的小端字符串 }
	 * @param entity
	 * @return
	 */
	public static String getCRC16(TCPEntity entity) {
		// CRC16校验
		byte[] crc16_data = CodeUtil.hexStringToBytes(entity.getSADR()
				+ entity.getDADR() + entity.getPORT() + entity.getFLAG()
				+ entity.getCMD() + entity.getLEN() + entity.getDATA());

		return CodeUtil.CRC16Table(crc16_data);
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月20日 下午3:41:47
	 * @Description {获取DATA 中的ID指令列表}
	 * @param DATA
	 * @return
	 */
	public static List<MYID> GetIDList(String DATA) {
		// 创建数组,保存指令ID
		List<MYID> ids = new ArrayList<MYID>();
		// 解析指令ID,保存到数据
		while (DATA.length() > 0) {
			MYID my_id = new MYID();
			String id = DATA.substring(0, 4);
			// 裁剪DATA
			DATA = DATA.substring(4, DATA.length());
			int a = CodeUtil.HexStringToInt(id);
//			System.out.println("a  :"+a);
			int id_len = ID_MAP.getID_Map().get(String.valueOf(a));
			String id_info = DATA.substring(0, id_len * 2);
			// 裁剪DATA
			DATA = DATA.substring(id_len * 2, DATA.length());
			my_id.ID = id;
			my_id.ID_INFO = id_info;
			ids.add(my_id);
		}
		return ids;
	}
}
